void* inputdata, int inputstride, void *userdata)
{
int alignment = STANDARD_ALIGNMENT;
- int stride = (img->get_width(cIdx) + alignment-1) / alignment * alignment;
- int height = img->get_height(cIdx);
+ uint32_t stride = (img->get_width(cIdx) + alignment-1) / alignment * alignment;
+ uint32_t height = img->get_height(cIdx);
- uint8_t* p = (uint8_t *)ALLOC_ALIGNED_16(stride * height + MEMORY_PADDING);
+ // size computed in size_t: stride*height can exceed UINT32_MAX for large planes
+ uint8_t* p = static_cast<uint8_t*>(ALLOC_ALIGNED_16(static_cast<size_t>(stride) * height + MEMORY_PADDING));
if (p==NULL) { return NULL; }
// copy input data if provided
- if (inputdata != NULL) {
- if (inputstride == stride) {
- memcpy(p, inputdata, stride*height);
+ if (inputdata != nullptr) {
+ if (inputstride == static_cast<int>(stride)) {
+ memcpy(p, inputdata, static_cast<size_t>(stride) * height);
}
else {
- for (int y=0;y<height;y++) {
- memcpy(p+y*stride, ((char*)inputdata) + inputstride*y, inputstride);
+ for (uint32_t y=0;y<height;y++) {
+ memcpy(p + static_cast<size_t>(y) * stride,
+ static_cast<char*>(inputdata) + static_cast<size_t>(inputstride) * y,
+ inputstride);
}
}
}
static int de265_image_get_buffer(de265_decoder_context* ctx,
de265_image_spec* spec, de265_image* img, void* userdata)
{
- const int rawChromaWidth = spec->width / img->SubWidthC;
- const int rawChromaHeight = spec->height / img->SubHeightC;
+ const uint32_t rawChromaWidth = spec->width / img->SubWidthC;
+ const uint32_t rawChromaHeight = spec->height / img->SubHeightC;
- int luma_stride = (spec->width + spec->alignment-1) / spec->alignment * spec->alignment;
- int chroma_stride = (rawChromaWidth + spec->alignment-1) / spec->alignment * spec->alignment;
+ uint32_t luma_stride = (spec->width + spec->alignment-1) / spec->alignment * spec->alignment;
+ uint32_t chroma_stride = (rawChromaWidth + spec->alignment-1) / spec->alignment * spec->alignment;
assert(img->BitDepth_Y >= 8 && img->BitDepth_Y <= 16);
assert(img->BitDepth_C >= 8 && img->BitDepth_C <= 16);
- int luma_bpl = luma_stride * ((img->BitDepth_Y+7)/8);
- int chroma_bpl = chroma_stride * ((img->BitDepth_C+7)/8);
+ uint32_t luma_bpl = luma_stride * ((img->BitDepth_Y+7)/8);
+ uint32_t chroma_bpl = chroma_stride * ((img->BitDepth_C+7)/8);
- int luma_height = spec->height;
- int chroma_height = rawChromaHeight;
+ uint32_t luma_height = spec->height;
+ uint32_t chroma_height = rawChromaHeight;
bool alloc_failed = false;
- uint8_t* p[3] = { 0,0,0 };
- p[0] = (uint8_t *)ALLOC_ALIGNED_16(luma_height * luma_bpl + MEMORY_PADDING);
- if (p[0]==NULL) { alloc_failed=true; }
+ // Compute the plane sizes in size_t. Each operand fits in uint32_t, but the
+ // height * bytes-per-line product can exceed UINT32_MAX for large frames, so
+ // the multiplication must be done in 64 bits. Computing it in 32 bits wraps
+ // the allocation size to a small value while fill_image() later writes the
+ // real (size_t) size -> heap buffer overflow (GHSA-vv8h-932h-7r86).
+ uint8_t* p[3] = { nullptr,nullptr,nullptr };
+ p[0] = static_cast<uint8_t*>(ALLOC_ALIGNED_16(static_cast<size_t>(luma_height) * luma_bpl + MEMORY_PADDING));
+ if (p[0]==nullptr) { alloc_failed=true; }
if (img->get_chroma_format() != de265_chroma_mono) {
- p[1] = (uint8_t *)ALLOC_ALIGNED_16(chroma_height * chroma_bpl + MEMORY_PADDING);
- p[2] = (uint8_t *)ALLOC_ALIGNED_16(chroma_height * chroma_bpl + MEMORY_PADDING);
+ p[1] = static_cast<uint8_t*>(ALLOC_ALIGNED_16(static_cast<size_t>(chroma_height) * chroma_bpl + MEMORY_PADDING));
+ p[2] = static_cast<uint8_t*>(ALLOC_ALIGNED_16(static_cast<size_t>(chroma_height) * chroma_bpl + MEMORY_PADDING));
if (p[1]==NULL || p[2]==NULL) { alloc_failed=true; }
}